#include "buffer.h"

#define BUFFER_MODE_WRITE 0U
#define BUFFER_MODE_READ  1U

void Buffer_Init(buffer_t *thiz, uint8_t *headPtr, uint32_t capacity) {
    assert_param(thiz != NULL);
    assert_param(headPtr != NULL);
//    if (thiz == 0U) {
//        return;
//    }   
    thiz->HeadPtr = headPtr;
    thiz->Capacity = capacity;
    thiz->Position = 0U;
    thiz->Limit = 0U;
    thiz->Mode = BUFFER_MODE_WRITE;
}

void Buffer_Put(buffer_t *thiz, uint8_t data) {
    assert_param(thiz != NULL);
    assert_param(thiz->Mode != BUFFER_MODE_READ);
//	if (thiz == 0U) {
//		return;
//	}
//    if (thiz->Mode == BUFFER_MODE_READ) {
//        return;
//    }
    if (thiz->Position >= thiz->Capacity) {
        return;
    }
    *(thiz->HeadPtr + thiz->Position) = data;
    thiz->Position++;
}

void Buffer_Fill(buffer_t *thiz, uint8_t *dataPtr, uint32_t len) {
    assert_param(thiz != NULL);
    assert_param(dataPtr != NULL);
    assert_param(thiz->Mode != BUFFER_MODE_READ);
    assert_param(thiz->Position + len < thiz->Capacity);
//    if (thiz == 0U) {
//		return;
//	}
//    if (thiz->Mode == BUFFER_MODE_READ) {
//        return;
//    }
//    if (thiz->Position + len >= thiz->Capacity) {
//        return;
//    }
    for (uint32_t i = 0U; i < len; i++) {
        *(thiz->HeadPtr + thiz->Position + i) = *(dataPtr + i);
        thiz->Position++;
    }
}

void Buffer_Reset(buffer_t *thiz) {
    assert_param(thiz != NULL);
//    if (thiz == 0U) {
//		return;
//	}
    thiz->Mode = BUFFER_MODE_WRITE;
    thiz->Position = 0U;
    thiz->Limit = 0U;
}

void Buffer_Flip(buffer_t *thiz) {
    assert_param(thiz != NULL);
//    if (thiz == 0U) {
//		return;
//	}
    thiz->Limit = thiz->Position;
    thiz->Position = 0U;
    thiz->Mode = thiz->Mode == BUFFER_MODE_WRITE ? BUFFER_MODE_READ : BUFFER_MODE_WRITE;
}

bool Buffer_IsEmpty(buffer_t *thiz) {
    assert_param(thiz != NULL);
//    if (thiz == 0U) {
//		return 0U;
//	}
//    if (thiz->Mode == BUFFER_MODE_READ) {
//        return 0U;
//    }
    
    return thiz->Position == 0U;
}

bool Buffer_IsFull(buffer_t *thiz) {
    assert_param(thiz != NULL);
//    if (thiz == 0U) {
//		return 0U;
//	}
//    if (thiz->Mode == BUFFER_MODE_READ) {
//        return 0U;
//    }
    return thiz->Position >= thiz->Capacity;
}

bool Buffer_HasNext(buffer_t *thiz) {
    assert_param(thiz != NULL);
    assert_param(thiz->Mode != BUFFER_MODE_WRITE);
//    if (thiz == 0U) {
//		return NULL;
//	}
//    if (thiz->Mode == BUFFER_MODE_WRITE) {
//        return NULL;
//    }
    return thiz->Position < thiz->Limit;
}

uint8_t Buffer_Next(buffer_t *thiz) {
    assert_param(thiz != NULL);
    assert_param(thiz->HeadPtr != NULL);
    assert_param(thiz->Mode != BUFFER_MODE_WRITE);
//    if (thiz == 0U) {
//		return NULL;
//	}
//    if (thiz->Mode == BUFFER_MODE_WRITE) {
//        return NULL;
//    }
    return *(thiz->HeadPtr + thiz->Position++);
}
